package ce.com.cenewbluesdk.ota.ota_modea;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;


import ce.com.cenewbluesdk.entity.k6.K6_OTAStateInfo;
import ce.com.cenewbluesdk.proxy.CEDevK6Proxy;
import ce.com.cenewbluesdk.uitl.CEBlueSharedPreference;
import ce.com.cenewbluesdk.uitl.Lg;


/**
 * Created by Administrator on 2016/1/8 0008.
 */
public class OtaK6Control {
    public static final int STATE_NONE = 0;
    public static final int STATE_NEED_UPDATE = 1;
    public static final int STATE_DOWNLOADING = 2;
    public static final int STATE_READY_OK = 3;
    public static final int STATE_HAS_DEV_STATE = 4;
    public static final int STATE_SENDING = 5;
    public static final int STATE_SENT = 6;
    public static final int STATE_CRC_OK = 7;


    private CEDevK6Proxy proxy;
    private Context mContext;

    private boolean needSendOTAInfoToMain = false;

    public void setNeedSendOTAInfoToMain(boolean needSendOTAInfoToMain) {
        this.needSendOTAInfoToMain = needSendOTAInfoToMain;
    }

    /**
     * ota 的升级状态
     * 0 没有升级
     * 1 需要升级
     * 2 现在文件
     * 3 文件处理OK  请求ota 升级状态
     * 4 获取到OTA升级状态，根据根据状态做对应的OTA处理。
     * 5 正在发送OTA数据
     * 6 ota 数据全部发送完成
     * 7 设备侧回复整个升级文件CRC校验通过，OTA数据发送成功
     */
    private int otaState = 0;

    private void setOtaState(int state) {
        if (otaState != state) {
            otaState = state;
//            App.getInstance().setOTAstate(state);
            //  EventAmanager.post(C.event.ACTION_BLUETOOTH_OTA_STATE_INFO_K3, state);
        }

    }

    private Messenger mainMessenger;

    public void setMainMessenger(Messenger mainMessenger) {
        this.mainMessenger = mainMessenger;
    }

    private OtaInfo mOtaK3Info = new OtaInfo();

    private int otaPos;
    /**
     * 发送OTA包最大失败次数
     */
    private static final int OTA_SEND_FILE_MAX_TIME = 5;
    private int otaSendFileMAXTime = OTA_SEND_FILE_MAX_TIME;

    /**
     * 请求OTA失败的最大次数
     */
    private static final int OTA_STATE_MAX_TIME = 3;
    private int getOtaStateMAXTime = OTA_STATE_MAX_TIME;

    public static final String OTA_INFO_DATA = "OTA_INFO_DATA_xxxdjdjjd";

    private OTASendEntity mOTASendEntity;

    private static String otaFilePath = Environment.getExternalStorageDirectory() + "/celink"+ "/K6_watch_device(V2.0.2.0.0).img";

    public OtaK6Control(CEDevK6Proxy proxy, Context mContext) {
        this.proxy = proxy;
        this.mContext = mContext;
    }

    public void startOta(String netVersion, String devString, String otaFileUrl) {
        otaLog("otaState=" + otaState);

        if (netVersion == null || devString == null || otaFileUrl == null) {
            return;
        }
        if (otaState > 0) {
            return;
        }

        otaLog("devV=" + devString + "  netV=" + netVersion);
        dealOTAUpdata(otaFileUrl, devString, netVersion);


    }


    public void otaDataSendResult(int result) {
        if (result == 1) {
            setOtaState(STATE_SENDING);
            otaSendFileMAXTime = OTA_SEND_FILE_MAX_TIME;
            otaPos = otaPos + mOTASendEntity.getLastSendBytesLen();
            long keng = ((long) otaPos) * 1000l;
            mOtaK3Info.setFileSize(mOTASendEntity.getOtaFileLen());
            mOtaK3Info.setOtaPos(otaPos);
            if (mOTASendEntity.getOtaFileLen() != 0)
                mOtaK3Info.setBaifenbi(keng / mOTASendEntity.getOtaFileLen());
//            if (App.getInstance().getOTAInfoDataChangeListen() != null) {
//                App.getInstance().getOTAInfoDataChangeListen().otaInfo(mOtaK3Info);
//            }
//            if (needSendOTAInfoToMain && mainMessenger != null) {
//                Message message = Message.obtain();
//                message.what = BC.CMD.ACTION_OTA_UPDATE_INFO.hashCode();
//                Bundle b = new Bundle();
//                b.putSerializable("data", mOtaK3Info);
//                message.setData(b);
//                try {
//                    mainMessenger.send(message);
//                } catch (RemoteException e) {
//                    e.printStackTrace();
//                }
//            }


            if (otaPos >= mOTASendEntity.getOtaFileLen()) {
                otaLog("ota 完成");
                setOtaState(STATE_SENT);
                return;
            }
            otaLog("ota otaPos=" + otaPos + "   all Len=" + mOTASendEntity.getOtaFileLen());
            proxy.getSendHelper().sendOTAData(mOTASendEntity.getOtaFileCRC()
                    , mOTASendEntity.getOtaFileLen(), otaPos, mOTASendEntity.getSendIndexDate(otaPos));
        } else {
            otaSendFileMAXTime--;
            if (otaSendFileMAXTime < 0) {
                setOtaState(STATE_NONE);
            } else {
                getOTAState();
            }
            otaLog("ota 失败  剩余失败次数：" + otaSendFileMAXTime);
        }
    }

    private static void otaLog(String s) {
        Lg.e("OTA 升级:" + s);
    }


    public void otaStateResult(K6_OTAStateInfo otaStateInfo) {
        otaSendFileMAXTime = OTA_SEND_FILE_MAX_TIME; //获取到了OTA的状态，将最大次数复位

//        OTAStateInfo otaStateInfo = (OTAStateInfo) event.obj;
//                if(otaStateInfo.getFile_crc16()!=)
        otaPos = otaStateInfo.getFile_pos();

        otaLog(otaStateInfo.toString());
        // switch (otaStateInfo.getStatus()) {
        if (otaStateInfo.getStatus() == OTASendEntity.OTA_NONE || otaStateInfo.getStatus() == OTASendEntity.OTA_RUNING) {
            if (otaState >= STATE_HAS_DEV_STATE) {
                return;
            }
            setOtaState(STATE_HAS_DEV_STATE);
        } else if (otaStateInfo.getStatus() == OTASendEntity.OTA_FINISH_SUCCESS) {
            setOtaState(STATE_CRC_OK);
        } else {
            setOtaState(STATE_NONE);
        }
        switch (otaStateInfo.getStatus()) {
            case 0:
                otaPos = 0;
                proxy.getSendHelper().sendOTAData(mOTASendEntity.getOtaFileCRC()
                        , mOTASendEntity.getOtaFileLen(), otaPos, mOTASendEntity.getSendIndexDate(otaPos));
                otaLog("没有升级过，从头开始升级");
                break;
            case 1:
                if (mOTASendEntity.getOtaFileCRC() == otaStateInfo.getFile_crc16()) {
                    otaPos = otaStateInfo.getFile_pos();
                    proxy.getSendHelper().sendOTAData(mOTASendEntity.getOtaFileCRC()
                            , mOTASendEntity.getOtaFileLen(), otaPos, mOTASendEntity.getSendIndexDate(otaPos));
                    otaLog("有升级过，从+" + otaPos + "+开始升级");
                } else {
                    otaPos = 0;
                    proxy.getSendHelper().sendOTAData(mOTASendEntity.getOtaFileCRC()
                            , mOTASendEntity.getOtaFileLen(), otaPos, mOTASendEntity.getSendIndexDate(otaPos));
                    otaLog("有升级过，但是crc校验不正确");
                }
                break;
            case 2:
                otaLog("升级成功");
                mOtaK3Info.setFileSize(mOTASendEntity.getOtaFileLen());
                mOtaK3Info.setOtaPos(mOTASendEntity.getOtaFileLen());
                if (mOTASendEntity.getOtaFileLen() != 0)
                    mOtaK3Info.setBaifenbi(1000);
//                if (needSendOTAInfoToMain && mainMessenger != null) {
//                    Message message = Message.obtain();
//                    message.what = BC.CMD.ACTION_OTA_UPDATE_INFO.hashCode();
//                    Bundle b = new Bundle();
//                    b.putSerializable("data", mOtaK3Info);
//                    message.setData(b);
//                    try {
//                        mainMessenger.send(message);
//                    } catch (RemoteException e) {
//                        e.printStackTrace();
//                    }
//                }
                break;
            case 3:
                otaLog("升级错误");
                break;
            case 4:
                otaLog("升级错我");
                break;
            case 5:
                otaLog("升级错我");
                break;
            default:
                otaLog("升级错我");
                break;
        }
    }

    public void bleStateChange() {
        if (proxy != null) {
            if (proxy.isDisconnect()) {
                setOtaState(STATE_NONE);
                mOtaK3Info = new OtaInfo();
            } else if (proxy.isConnectOK()) {
                otaSendFileMAXTime = OTA_SEND_FILE_MAX_TIME;
                getOtaStateMAXTime = OTA_STATE_MAX_TIME;
            }
        }
    }

    public void getOTAInfoResult(int state) {
        if (state == 0) {  // OTA状态获取失败  需要重新获取
            getOtaStateMAXTime--;
            if (getOtaStateMAXTime < 0) {
                setOtaState(STATE_NONE);
            } else {
                getOTAState();
            }

        }
    }


    private String netVersion;//需要升级的版本号
    private String OTAFileUrl;
    private String devVersion;//设备侧的版本号

    private void  dealOTAUpdata(String otaFileUrl, String devV, String netV) {
        if (needOTA(devV, netV)) {
            setOtaState(STATE_NEED_UPDATE);
            netVersion = netV;
            OTAFileUrl = otaFileUrl;
            devVersion = devV;

            mOtaK3Info.setNetVersion(netV);
            mOtaK3Info.setDevVersion(devV);

            if (true||netV.equals(CEBlueSharedPreference.getInstance(mContext).getNewK3OTAFileVersion())) {
                otaLog("存储的版本号和服务器一样，不需要下载文件，直接升级");
                processOtaFile(OtaUtil.getBytes(otaFilePath), true);
            } else {
                new UpdateTask().execute();
            }

        }
    }

    private void getOTAState() {
        if (proxy != null &&
                proxy.isConnectOK()) {
            setOtaState(STATE_READY_OK);
            proxy.getSendHelper().getOTAState();
        } else {
            setOtaState(STATE_NONE);
        }
    }

    //  2016/2/2 完全没考虑线程问题, 可能有隐患 // 应该不会有问题，每次只会启动一个线程
    private boolean processOtaFile(byte[] ota, boolean nendUpdateOTAFile) {
        try {
            DealOtaFile otaFile = new DealOtaFile(ota);
            mOTASendEntity = otaFile.getOTASendEntity();
            Map<Integer, Integer> netVersionMap = OtaUtil.versionStr2Map(netVersion);
            Map<Integer, Integer> fileVersionMap = mOTASendEntity.getVersionMap();
            Map<Integer, Integer> devVersionMap = OtaUtil.versionStr2Map(devVersion);
            otaLog("net=" + netVersionMap + ", file=" + fileVersionMap + ", dev=" + devVersionMap);
            // 比较网络版本号和文件版本号
            if (!OtaUtil.equalVersionMap(netVersionMap, fileVersionMap)) {
                throw new OtaFileException("网络版本号和文件版本号不一致" + ", net=" + netVersionMap + ", file=" + fileVersionMap + ", dev=" + devVersionMap);
            }
            setOtaState(STATE_READY_OK);
            mOTASendEntity.initOTAData(devVersionMap);
            getOTAState();
            return true;
        } catch (OtaFileException e) {
//            CrashHelper.log(e, otaLog("ota文件错误" + e.getMessage() + ", 需要重新下载=" + nendUpdateOTAFile));
            if (nendUpdateOTAFile) {
                new UpdateTask().execute();
            } else {
                setOtaState(STATE_NONE);
            }
            return false;
        }
    }

//    private void startOTA(boolean nendUpdateOTAFile) {
//        if (mDealOtaFile.getOTASendEntity() == null ||
//                !mDealOtaFile.getOTASendEntity().isOtaSendEntityIsOK()) {
//            DealOtaFile.otaLog("ota文件错误，需要重新下载" + mDealOtaFile.getOTAFileErrorString());
//            if (nendUpdateOTAFile) {
//                new UpdateTask().execute();
//            } else {
//                setOtaState(STATE_NONE);
//            }
//        } else {
//            setOtaState(STATE_READY_OK);
//            mOTASendEntity = mDealOtaFile.getOTASendEntity();
//            mOTASendEntity.initOTAData(versionStr2Map());
//            getOTAState();
//        }
//    }

    public static boolean needOTA(String devV, String netV) {
        if (devV == null || netV == null) {
            return false;
        }
        String[] dstrings = devV.split("\\.");
        String[] nstrings = netV.split("\\.");
        if (dstrings.length != 5 || nstrings.length != 5) {// 判断
            otaLog("解析出来的版本号长度不等于5   dev=" + dstrings.toString() + "   net= " + nstrings.toString());
            return false;
        }
        if (!dstrings[0].trim().equals(nstrings[0].trim())) {
            otaLog("不是同一个客户的   dev=" + dstrings[0] + "   net= " + nstrings[0]);
            return false;
        }


        try {
            //  2016/2/2 比较有问题  不会有问题，因为版本号只会变大，不会变小

            //  不需要比对 index 等于1 是因为 是硬件版本号， index 5 最后一个是字库,也不需要比对
            String d = dstrings[0] + dstrings[2] + dstrings[3];
            String n = nstrings[0] + nstrings[2] + nstrings[3];
//            return !d.equals(n);
//            String d = devV.trim().replace(".", "");
//            String n = netV.trim().replace(".", "");
            int dev = Integer.parseInt(d);
            int net = Integer.parseInt(n);
            return net > dev;
        } catch (Exception e) {
            otaLog("OTA版本比对错误" + e.toString());
            return false;
        }
    }

    //下载bin文件方法
    public static byte[] getBinFromServer(String path) throws Exception {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        // 获取到文件的大小
        int ifileLength = conn.getContentLength();
        byte[] myByte = new byte[ifileLength];
        InputStream is = conn.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        byte[] buffer = new byte[1024];
        int len;
        int total = 0;
        otaLog("ifileLength=" + ifileLength);
        // &&!isActivityBack
        while ((len = bis.read(buffer)) != -1) {
            System.arraycopy(buffer, 0, myByte, total, len);
            total += len;
        }
        bis.close();
        is.close();
        otaLog("myByte=" + myByte.length);
        return myByte;
    }

    private class UpdateTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                setOtaState(STATE_DOWNLOADING);
                byte[] bytes = getBinFromServer(OTAFileUrl);
                if (processOtaFile(bytes, false)) {
                    writeFile(bytes);
                }
            } catch (Exception e) {
                setOtaState(STATE_NONE);
                otaLog(e.toString());
                e.printStackTrace();

            }
            return null;
        }
    }

    private void writeFile(byte[] bytes) {
        //建立输出字节流
        FileOutputStream fos = null;
        File file = new File(otaFilePath);
        if (file.exists()) {
            file.delete();
        }
        try {
            file.createNewFile();
            fos = new FileOutputStream(file);
            //用FileOutputStream 的write方法写入字节数组
            fos.write(bytes);
            System.out.println("写入成功");

            //为了节省IO流的开销，需要关闭
            CEBlueSharedPreference.getInstance(mContext).setNewK3OTAFileVersion(netVersion);

        } catch (Exception e) {
            e.printStackTrace();
            // TODO: 2016/2/2 抛异常时流没关闭
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
